﻿Imports System
Imports System.ComponentModel
Imports System.Globalization
Imports System.Runtime.InteropServices
Imports System.Workflow.Activities.Rules.Design
Imports System.Workflow.ComponentModel
Imports System.Workflow.ComponentModel.Compiler
Imports System.Workflow.ComponentModel.Design

Namespace System.Workflow.Activities.Rules
    <TypeConverter(GetType(RuleConditionReferenceTypeConverter)), ActivityValidator(GetType(RuleConditionReferenceValidator)), SRDisplayName("RuleConditionDisplayName")> _
    Public Class RuleConditionReference
        Inherits ActivityCondition
        ' Methods
        Public Overrides Function Evaluate(ByVal activity As Activity, ByVal provider As IServiceProvider) As Boolean
            If (activity Is Nothing) Then
                Throw New ArgumentNullException("activity")
            End If
            If String.IsNullOrEmpty(Me._condition) Then
                Throw New InvalidOperationException(SR.GetString("Error_MissingConditionName", New Object() { activity.Name }))
            End If
            Dim ruleDefinitions As RuleDefinitions = Nothing
            If String.IsNullOrEmpty(Me.declaringActivityId) Then
                Dim declaringActivity As CompositeActivity = Nothing
                ruleDefinitions = RuleConditionReference.GetRuleDefinitions(activity, declaringActivity)
            Else
                ruleDefinitions = DirectCast(activity.GetActivityByName(Me.declaringActivityId).GetValue(RuleDefinitions.RuleDefinitionsProperty), RuleDefinitions)
            End If
            If ((ruleDefinitions Is Nothing) OrElse (ruleDefinitions.Conditions Is Nothing)) Then
                Throw New InvalidOperationException(SR.GetString("Error_MissingRuleConditions"))
            End If
            Dim condition As RuleCondition = ruleDefinitions.Conditions.Item(Me._condition)
            If (condition Is Nothing) Then
                Return True
            End If
            Dim enclosingActivity As Activity = Helpers.GetEnclosingActivity(activity)
            Dim validation As New RuleValidation(enclosingActivity)
            If Not condition.Validate(validation) Then
                Throw New InvalidOperationException(String.Format(CultureInfo.CurrentCulture, Messages.ConditionValidationFailed, New Object() { Me._condition }))
            End If
            Dim execution As New RuleExecution(validation, enclosingActivity, [TryCast](provider,ActivityExecutionContext))
            Return condition.Evaluate(execution)
        End Function

        Private Shared Function GetRuleDefinitions(ByVal activity As Activity, <Out> ByRef declaringActivity As CompositeActivity) As RuleDefinitions
            declaringActivity = Helpers.GetDeclaringActivity(activity)
            If (declaringActivity Is Nothing) Then
                declaringActivity = [TryCast](Helpers.GetRootActivity(activity),CompositeActivity)
            End If
            Return ConditionHelper.Load_Rules_RT(declaringActivity)
        End Function

        Protected Overrides Sub InitializeProperties()
            SyncLock Me.syncLock
                If Not Me._runtimeInitialized Then
                    Dim declaringActivity As CompositeActivity = Nothing
                    Dim parentDependencyObject As Activity = [TryCast](MyBase.ParentDependencyObject,Activity)
                    RuleConditionReference.GetRuleDefinitions(parentDependencyObject, declaringActivity).OnRuntimeInitialized
                    Me.declaringActivityId = declaringActivity.QualifiedName
                    MyBase.InitializeProperties
                    Me._runtimeInitialized = True
                End If
            End SyncLock
        End Sub


        ' Properties
        Public Property ConditionName As String
            Get
                Return Me._condition
            End Get
            Set(ByVal value As String)
                Me._condition = value
            End Set
        End Property


        ' Fields
        Private _condition As String
        Private _runtimeInitialized As Boolean
        Private declaringActivityId As String = String.Empty
        <NonSerialized> _
        Private [syncLock] As Object = New Object
    End Class
End Namespace

